﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NHibernate.Cfg;
using System.Collections;
using FluentNHibernate.Cfg;
using FluentNHibernate.Mapping;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using NHibernate.Connection;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Testing;

namespace InnovTech.Data.NHibernate.Test
{

    public static class TestUtil
    {

        public static Configuration CreateFluentConfig()
        {
            FluentConfiguration cfg = 
             Fluently.Configure()
                           .Database(SQLiteConfiguration.Standard.InMemory().Raw("connection.release_mode", "on_close")
                           //.Driver("NHibernate.Driver.SQLite20Driver")
                           //.Dialect("NHibernate.Dialect.SQLiteDialect")
                           .Provider("InnovTech.Data.NHibernate.Test.SqLiteInMemoryTestingConnectionProvider, InnovTech.Data.NHibernate.Test")
                           //.Provider("FluentNHibernate.Testing.SingleConnectionSessionSourceForSQLiteInMemoryTesting, FluentNHibernate")
                           //.ConnectionString("Data Source=:memory:;Version=3;New=True;")
                           )
                           .Mappings(m => m.FluentMappings.Add(typeof(PersonFluentMapping)))
                           .Mappings(m => m.FluentMappings.Add(typeof(PetMapping)));

            Configuration config = cfg.BuildConfiguration();
            return config;
        }

        static ISessionFactory TestSessionFactory;
        public static ISessionFactory CreateTestDB()
        {
            Configuration config = CreateFluentConfig();
            TestSessionFactory = config.BuildSessionFactory();
            new SchemaExport(config).Create(false, true);
            return TestSessionFactory;
        }

        public static void CloseTestDB()
        {
            SqLiteInMemoryTestingConnectionProvider.CloseSqLiteInMemoryDBConnection();
        }
    }

    public class Person
    {
        public virtual long ID { get; set; }
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
        public virtual Person Friend { get; set; }
        public virtual IList<Pet> Pets { get; set; }
    }

    public class PersonFluentMapping : ClassMap<Person>
    {
        public PersonFluentMapping()
        {
            Table("Persons");
            Id(p => p.ID).Column("ID");
            Map(p => p.FirstName).Not.Nullable();
            Map(p => p.LastName).Column("Name").Not.Nullable();
            References(p => p.Friend).Column("FriendId");
            HasMany(p => p.Pets).Cascade.All().KeyColumn("PetId");
        }
    }

    public class Pet
    {
        public virtual string Name { get; set; }
        public virtual long ID { get; set; }
        public virtual Person Owner { get; set; }
    }

    public class PetMapping : ClassMap<Pet>
    {
        public PetMapping()
        {
            Table("Pets");
            Id(p => p.ID).Column("ID");
            Map(p => p.Name).Column("Name");
            References(p => p.Owner).Column("OwnerId");
        }
    }

    public class SqLiteInMemoryTestingConnectionProvider : DriverConnectionProvider
    {
        public static System.Data.IDbConnection Connection = null; 
        public override System.Data.IDbConnection GetConnection() 
        { 
            if (Connection == null)             
                Connection = base.GetConnection(); 
            return Connection; 
        }     
        public override void CloseConnection(System.Data.IDbConnection conn) { }

        public static void CloseSqLiteInMemoryDBConnection()
        {
            if (Connection != null)
            {
                if (Connection.State != System.Data.ConnectionState.Closed)
                    Connection.Close();
                Connection = null;
            }
        }
    }  
}
